
package com.be.beadmin.service.impl;

import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.utils.JpaQueryBuilderNew;
import com.be.beadmin.service.dto.input.NotifyInfoTotalByPage;
import com.be.beadmin.service.dto.output.NotifyInfoTotalEx;
import com.be.beadmin.service.entity.*;
import cn.hutool.core.util.ObjectUtil;

import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.service.repository.InspectTaskRepository;
import com.be.beadmin.service.repository.NotifyInfoRepository;
import lombok.RequiredArgsConstructor;
import com.be.beadmin.service.mapper.NotifyTemplateInfoMapperEx;
import com.be.beadmin.service.repository.NotifyTemplateInfoRepository;
import com.be.beadmin.service.service.NotifyTemplateInfoService;
import com.be.beadmin.service.dto.input.NotifyTemplateInfoDto;
import com.be.beadmin.service.dto.output.NotifyTemplateInfoEx;
import com.be.beadmin.service.dto.input.NotifyTemplateInfoQueryCriteria;
import com.be.beadmin.service.mapper.NotifyTemplateInfoMapper;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Order;
import java.time.LocalDate;
import java.util.*;

/**
* @description 服务实现
* @author ljh
* @date 2023-09-20
**/
@Service
@RequiredArgsConstructor
public class NotifyTemplateInfoServiceImpl implements NotifyTemplateInfoService {

    @Autowired
    private  NotifyTemplateInfoRepository notifyTemplateInfoRepository;
    @Autowired
    private  NotifyTemplateInfoMapper notifyTemplateInfoMapper;
    @Autowired
    private  NotifyTemplateInfoMapperEx notifyTemplateInfoExMapper;

    @Autowired
    private NotifyInfoRepository notifyInfoRepository;

    @Autowired
    private WebSocketNotifyService webSocketNotifyService;

    @Autowired
    private InspectTaskRepository inspectTaskRepository;


    @Override
    public Page<NotifyTemplateInfoEx> getNotifyTemplateInfoByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<NotifyTemplateInfo> page = notifyTemplateInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(NotifyTemplateInfo_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(NotifyTemplateInfo_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<NotifyTemplateInfoEx> page1 = page.map(notifyTemplateInfoExMapper::toEntity);
            return page1;

    }


    @Override
    public Page<NotifyInfoTotalEx> getNotifyInfoTotalByPage2(NotifyInfoTotalByPage notifyInfoTotalByPage) {

        String sortField = notifyInfoTotalByPage.getSortField();
        Boolean desc = notifyInfoTotalByPage.getDesc();

        if (sortField == null || sortField.isEmpty()){
            throw new BeadminException("请设置排序字段");
        }

        if (desc == null){
            throw new BeadminException("请设置排序顺序");
        }

        Sort sort = desc ? new Sort(Sort.Direction.DESC, sortField):new Sort(Sort.Direction.ASC,sortField);
        Pageable pageable = PageRequest.of(
                notifyInfoTotalByPage.getPageNum()-1,
                notifyInfoTotalByPage.getPageSize(),sort);

        return notifyInfoRepository.getNotifyInfoTotalByPage(notifyInfoTotalByPage,pageable);

    }

//    @Override
//    public Page<NotifyInfoTotalEx> getNotifyInfoTotalByPage(NotifyInfoTotalByPage notifyInfoTotalByPage) {
//        PageEntity pageEntity = notifyInfoTotalByPage.getPageEntity();
//        String notifyType = notifyInfoTotalByPage.getNotifyType();
//        String receiverName = notifyInfoTotalByPage.getUserName();
//
//        Pageable pageable = PageRequest.of(
//                pageEntity.getCurrent() -1,
//                pageEntity.getPageSize());
//
//        Page<NotifyTemplateInfo> page = notifyTemplateInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
//            List<Predicate> list = new ArrayList<>();
//            Predicate pre1 =   JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
//            list.add(pre1);
//            Predicate pre2 = criteriaBuilder.equal(root.get(NotifyTemplateInfo_.delete), 0); //过滤为0
//            list.add(pre2);
//            Predicate pre3 = criteriaBuilder.equal(root.get(NotifyTemplateInfo_.notifyType), notifyType);
//            list.add(pre3);
//            Predicate pre4 = criteriaBuilder.equal(root.get(NotifyTemplateInfo_.receiverName), receiverName);
//            list.add(pre4);
//            Predicate[] p = new Predicate[list.size()];
//            List<Order> orders = new ArrayList<>();
//            if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
//                orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
//                criteriaQuery.orderBy(orders);
//            } else {
//                criteriaQuery.orderBy(criteriaBuilder.desc(root.get(NotifyTemplateInfo_.createTime).as(Date.class)));
//            }
//            return  criteriaBuilder.and(list.toArray(p));
//        }
//        , pageable);
//
//        List<String> notifyInfoIds = page.stream().map(NotifyTemplateInfo::getNotifyInfoId).collect(Collectors.toList());
//
//        List<NotifyInfo> notifyInfoList = notifyInfoRepository.findByIdIn(notifyInfoIds);                       // in 查询优化
//
//
////        Page<NotifyTemplateInfo> page = notifyTemplateInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
////            List<Predicate> predicates = new ArrayList<>();
////            predicates.add(criteriaBuilder.equal(root.get("notifyType"), notifyType));
////            predicates.add(criteriaBuilder.equal(root.get("receiverName"), receiverName));
////            return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
////        }
////        , pageable);
//
//        return page.map (item -> {
//            NotifyInfoTotalEx notifyInfoTotalEx = new NotifyInfoTotalEx();
//            NotifyInfo notifyInfo = notifyInfoList.stream().filter(s -> s.getId().equals(item.getNotifyInfoId())).findFirst().orElse(null);
////            NotifyInfo notifyInfo = notifyInfoRepository.findNotifyInfoById(item.getNotifyInfoId());
//            assert notifyInfo != null;
//            notifyInfoTotalEx.setModuleName(notifyInfo.getModuleName());
//            notifyInfoTotalEx.setFuncName(notifyInfo.getFuncName());
//            notifyInfoTotalEx.setNotifyDesc(notifyInfo.getNotifyDesc());
//
//            notifyInfoTotalEx.setStatus(item.getStatus());
//            notifyInfoTotalEx.setNotifyType(item.getNotifyType());
//            notifyInfoTotalEx.setNotifyInfoId(item.getNotifyInfoId());
//            notifyInfoTotalEx.setNotifyTemplateInfoId(item.getId());
//            notifyInfoTotalEx.setReceiverId(item.getReceiverId());
//            notifyInfoTotalEx.setReceiverName(item.getReceiverName());
//            notifyInfoTotalEx.setSendTime(item.getSendTime());
//            notifyInfoTotalEx.setSenderId(item.getSenderId());
//            notifyInfoTotalEx.setSenderName(item.getSenderName());
//            return notifyInfoTotalEx;
//        });
//    }

    @Override
    public void readOneOrManyOrAllNotify(String userName,String notifyType,int status,List<String> notifyTemplateInfoIdList) {
        if(notifyTemplateInfoIdList!=null){
            List<String> notifyInfoIdList =new ArrayList<>();
            for(String notifyTemplateInfoId:notifyTemplateInfoIdList){
                NotifyTemplateInfo notifyTemplateInfo= notifyTemplateInfoRepository.findNotifyTemplateInfoByIdAndDelete(notifyTemplateInfoId,0);
                int status1 =notifyTemplateInfo.getStatus();
                if (status1 < 0) {
                    notifyTemplateInfo.setStatus(-status1);
                    notifyTemplateInfoRepository.save(notifyTemplateInfo);
                }
                notifyInfoIdList.add(notifyTemplateInfo.getNotifyInfoId());
            }

            List<NotifyInfo> notifyInfoList = notifyInfoRepository.findByIdIn(notifyInfoIdList);

            webSocketNotifyService.updateMessageToUser(notifyInfoList,userName);

        }else{
            List<NotifyTemplateInfo> notifyTemplateInfoList =  notifyTemplateInfoRepository.findNotifyTemplateInfoByReceiverNameAndStatusAndNotifyTypeAndDelete(userName,status,notifyType,0);
            for(NotifyTemplateInfo notifyTemplateInfo:notifyTemplateInfoList){
                int status1 =notifyTemplateInfo.getStatus();
                if (status1 < 0) {
                    notifyTemplateInfo.setStatus(-status1);
                }
            }
            notifyTemplateInfoRepository.saveAll(notifyTemplateInfoList);
        }
    }

    @Override
    public void readAllNotify(String userName, String notifyType, int status) {
        List<NotifyTemplateInfo> notifyTemplateInfoList = notifyTemplateInfoRepository.findNotifyTemplateInfoByReceiverNameAndStatusAndDelete(userName,status,0);
        for(NotifyTemplateInfo notifyTemplateInfo:notifyTemplateInfoList){
            int status1 =notifyTemplateInfo.getStatus();
            if (status1 < 0) {
                notifyTemplateInfo.setStatus(-status1);
            }
        }
        notifyTemplateInfoRepository.saveAll(notifyTemplateInfoList);
    }

    @Transactional
    @Override
    public void generateNotifyTemplateInfoOfInspectTask(String username, Date currentDate) {
        // 创建 Calendar 对象，并设置当前日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);

        // 设置开始时间为当天的0点
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date startTime = calendar.getTime();

        // 设置结束时间为当天的23点59分59秒
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        Date endTime = calendar.getTime();

        //所有没有发送过消息的任务
        List<InspectTask> inspectTaskList = inspectTaskRepository.findInspectTasksByInspectByAndDeleteAndIsNotifyAndPlanedTimeBefore(username,0,0,endTime);
        for(InspectTask inspectTask1:inspectTaskList){

                //定义消息实体notifyInfo
                NotifyInfo notifyInfo =new NotifyInfo();
                notifyInfo.setModuleName("设备管理");
                notifyInfo.setFuncName("巡检计划");

                notifyInfo.setNotifyDesc("巡检任务号为["+inspectTask1.getTaskId()+"],巡检任务待完成");
                notifyInfo.setNotifyType("待办");

                notifyInfo.setSenderName(inspectTask1.getCreateName());
                notifyInfo.setSenderId(inspectTask1.getCreateId());

                notifyInfo.setSendTime(currentDate);
                notifyInfo = notifyInfoRepository.save(notifyInfo);

                //调用发消息的接口
                sendNotify(notifyInfo,-1,username,null);

            inspectTask1.setIsNotify(1);
        }
        inspectTaskRepository.saveAll(inspectTaskList);
    }

    @Override
    public void addNotifyTemplateInfo(NotifyTemplateInfoDto notifyTemplateInfoDto) {
            NotifyTemplateInfo result = notifyTemplateInfoRepository.findNotifyTemplateInfoByIdAndDelete(notifyTemplateInfoDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("NotifyTemplateInfo不存在,请重新查询");
            }
            NotifyTemplateInfo notifyTemplateInfo = notifyTemplateInfoMapper.toEntity(notifyTemplateInfoDto);
            notifyTemplateInfoRepository.save(notifyTemplateInfo);
    }

    @Override
    public void updateNotifyTemplateInfo(NotifyTemplateInfoDto notifyTemplateInfoDto) {
            NotifyTemplateInfo notifyTemplateInfo = notifyTemplateInfoRepository.findNotifyTemplateInfoById(notifyTemplateInfoDto.getId());
            notifyTemplateInfo = notifyTemplateInfoMapper.toEntity(notifyTemplateInfoDto);
            notifyTemplateInfoRepository.save(notifyTemplateInfo);
    }


    @Override
    public void delNotifyTemplateInfo(String id) {
        //NotifyTemplateInfo notifyTemplateInfo = notifyTemplateInfoRepository.findNotifyTemplateInfoById(id);
//        notifyTemplateInfo.setDelete(1);
//        notifyTemplateInfoRepository.save(notifyTemplateInfo);
        notifyTemplateInfoRepository.deleteById(id);
    }

    @Override
    public void delNotifyTemplateInfos (String userName,int status) {
        List<NotifyTemplateInfo> notifyTemplateInfoList = notifyTemplateInfoRepository.findNotifyTemplateInfoByReceiverNameAndStatusAndDelete(userName,status,0);
        notifyTemplateInfoRepository.deleteAll(notifyTemplateInfoList);
    }

    /**
     * 查询未读或未处理的消息，
     * map：key发送人，val消息实体
     * @param username  接收人
     * @return
     */
    @Override
    public Map<String, List<Object>> findNotReadNotifyTemplateInfoOfUserName(String username) {
        //username 接收消息的人
        //map key：发送消息的人，value：消息集合
        List<NotifyTemplateInfo> notifyTemplateInfoList = notifyTemplateInfoRepository.findNotifyTemplateInfoByReceiverNameAndDeleteAndStatusLessThan(username,0,0);
        Map<String, List<Object>> map = new HashMap<>();
        for(NotifyTemplateInfo notifyTemplateInfo:notifyTemplateInfoList){
            String senderName = notifyTemplateInfo.getSenderName();
            String notifyInfoId = notifyTemplateInfo.getNotifyInfoId();
            if (notifyInfoId==null) continue;

            List<Object> notifyInfos=new ArrayList<>();
            if(map.get(senderName)!=null) notifyInfos =map.get(senderName);

            NotifyInfo notifyInfo = notifyInfoRepository.findNotifyInfoByIdAndDelete(notifyInfoId,0);
            notifyInfos.add(notifyInfo);
            map.put(senderName,notifyInfos);

        }
        return map;
    }

    @Override
    public Page<NotifyInfoTotalEx> getNotifyInfoTotalByPage(NotifyInfoTotalByPage notifyInfoTotalByPage) {
        return null;
    }

    /**
     * 业务逻辑中调用，发送消息
     *
     * @param notifyInfo
     * @param status
     * @param receiverName
     */
    @Override
    public void sendNotify(NotifyInfo notifyInfo,int status,String receiverName,String receiverId){
        NotifyTemplateInfo notifyTemplateInfo = new NotifyTemplateInfo();
        notifyTemplateInfo.setNotifyInfoId(notifyInfo.getId());
        notifyTemplateInfo.setNotifyType(notifyInfo.getNotifyType());
        notifyTemplateInfo.setStatus(status);//未处理
        notifyTemplateInfo.setSenderName(notifyInfo.getSenderName());
        notifyTemplateInfo.setSendTime(notifyInfo.getSendTime());
        notifyTemplateInfo.setReceiverName(receiverName);

        if(notifyInfo.getSenderId()!=null) notifyTemplateInfo.setSenderId(notifyInfo.getSenderId());
        if(receiverId!=null) notifyTemplateInfo.setReceiverId(receiverId);

        notifyTemplateInfo = notifyTemplateInfoRepository.save(notifyTemplateInfo);

        webSocketNotifyService.sendMessageToUser(notifyInfo,receiverName);
    }


}